package com.guzhi.domain;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.math.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.guzhi.common.Consts;
import com.guzhi.exception.GZException;
import com.guzhi.mapper.AdminMapper;
import com.guzhi.mapper.AlbumMapper;
import com.guzhi.mapper.DiscussionMapper;
import com.guzhi.mapper.FeedBackMapper;
import com.guzhi.mapper.ForgetPasswordMapper;
import com.guzhi.mapper.FriendshipMapper;
import com.guzhi.mapper.InteractMapper;
import com.guzhi.mapper.InteractStateMapper;
import com.guzhi.mapper.IntroMapper;
import com.guzhi.mapper.LeadPageMapper;
import com.guzhi.mapper.PostsMapper;
import com.guzhi.mapper.TestMapper;
import com.guzhi.mapper.UserMapper;
import com.guzhi.mapper.UserSetMapper;
import com.guzhi.mapper.UserTraceMapper;
import com.guzhi.utils.CryptUtil;
import com.guzhi.utils.UnicodeConverter;

/**
 * 
 * @author duanshao
 */
@Service("domainResource")
public class DomainResource {

    private final static Logger LOG = LoggerFactory.getLogger(DomainResource.class);

    @Autowired(required = true)
    private TestMapper testMapper;

    @Autowired(required = true)
    private UserMapper userMapper;

    @Autowired(required = true)
    private UserTraceMapper traceMapper;

    @Autowired(required = true)
    private InteractMapper interactMapper;

    @Autowired(required = true)
    private AlbumMapper albumMapper;

    @Autowired(required = true)
    private FeedBackMapper feedBackMapper;

    @Autowired(required = true)
    private LeadPageMapper leadPageMapper;

    @Autowired(required = true)
    private ForgetPasswordMapper forgetPasswordMapper;

    @Autowired(required = true)
    private IntroMapper introMapper;

    @Autowired(required = true)
    private FriendshipMapper friendshipMapper;

    @Autowired(required = true)
    private DiscussionMapper disMapper;

    @Autowired(required = true)
    private InteractStateMapper interactStateMapper;

    @Autowired(required = true)
    private PostsMapper postsMapper;

    @Autowired(required = true)
    private AdminMapper adminMapper;

    @Autowired(required = true)
    private UserSetMapper userSetMapper;

    public List<Test> queryAllTest() {
        return testMapper.queryAll();
    }

    public Test queryTestById(Long id) {
        return testMapper.queryTestById(id);
    }

    /* =========================用户注册============================ */

    /**
     * 创建用户，成功则返回gzno，否则返回null
     * 
     * @param nick 昵称
     * @param province 省下标
     * @param city 市下标
     * @param district 区下标
     * @param sex 性别
     * @param birth 生日
     * @param phone 手机
     * @param pwd 密码
     * @param hdLogo 高清图片
     * @param logo 个人头像
     * @return User-Bean or null
     */
    public User createUser(User user) {

        int index = (int) (NumberUtils.toLong(user.getPhone()) % Consts.TablePartition.USER); // 用户的手机号码
        // 表名
        String table = Consts.TablePrefix.USER + index;
        System.out.println(table);
        // 默认生成一个咕吱号，也必须符合%8=index
        int radix = index;
        String gzno = createGzno(radix);

        try {
            int times = 0;
            // 保证没有重复的咕吱号
            while (userMapper.hasGzno(table, gzno) > 0) {
                gzno = createGzno(radix);
                times++;
            }
            if (times >= 3) {
                LOG.warn("create Gzno repeat too many time s, phone:{},index:{},times:{}", user.getPhone(), index,
                        times);
            }
            LOG.info("create user, phone:{},index:{},gzno:{}", user.getPhone(), index, gzno);

            int result = userMapper.create(table, user, gzno, radix);
            if (result == 1) {
                user.setGzno(gzno);
                userMapper.createImidUserId(CryptUtil.md5(user.getPhone()), user.getId());
                return user;
            }
        } catch (Exception e) {
            LOG.error("create User error", e);
            throw new GZException(Consts.Code.INTERNAL_ERROR, e.getMessage());
        }
        return null;
    }

    /* =======================用户登录============================ */

    /**
     * 用户登陆 成功则返回User bean 否则返回null
     * 
     * @param userName 手机号或咕吱号
     * @param pwd 密码
     * @return User-Bean or null
     * */
    public User login(String userName, String pwd) {

        int index = (int) (NumberUtils.toLong(userName) % Consts.TablePartition.USER);

        String table = Consts.TablePrefix.USER + index;

        try {
            LOG.info("user login , userName:{}", userName);
            return userMapper.login(table, userName, pwd);
        } catch (Exception e) {
            LOG.error("user login error", e);
            throw new GZException(Consts.Code.INTERNAL_ERROR, e.getMessage());
        }

    }

    // 生成一个咕吱号 6到9位
    private static String createGzno(int radix) {
        int i = RandomUtils.nextInt(100000000);
        if (i < 100000) {
            i += 100000;
        }
        long gzno = i * 8 + radix;
        return String.valueOf(gzno);
    }

    public static void main(String[] args) {
        // 测试咕吱号的重复率,以及长度遍布
        // 测试结果100w,大概有500个人冲突,即万分之五,可以接受
        // 同时9位数的占了90%, 8位数的 9%, 7位数的0.9%, 6位数的 0.09%，
        // 符合越短位的越珍贵，FIXME 后期考虑靓号资源的释放
        Map<String, Integer> map = new HashMap<String, Integer>();
        Map<Integer, Integer> lenMap = new HashMap<Integer, Integer>();
        for (int i = 0; i < 1000000; i++) {
            String gzno = createGzno(7);
            Integer len = gzno.length();
            Integer lenVal = lenMap.get(len);
            if (lenVal == null) {
                lenMap.put(len, 1);
            } else {
                lenMap.put(len, lenVal + 1);
            }

            Integer count = map.get(gzno);
            if (count == null) {
                map.put(gzno, 1);
            } else {
                map.put(gzno, count + 1);
            }
        }
        Set<String> set = map.keySet();

        Iterator<String> it = set.iterator();

        while (it.hasNext()) {
            String key = it.next();
            Integer count = map.get(key);
            if (count >= 2) {
                System.out.println(key + "==" + count);
            }
        }

        System.out.println(lenMap);
    }

    /* ========================更新用户的IMID============================= */

    /**
     * 更新用户的IMID
     * 
     * @param phone 用户手机号码
     * @param uuid
     * @return int-type
     */
    public int updateImid(String phone) {
        try {
            return userMapper.updateImid(Consts.TablePrefix.USER
                    + (int) (NumberUtils.toLong(phone) % Consts.TablePartition.USER), phone);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /* ==========================查询附近的人============================== */

    private static final double LAT_LEN = 20003.93 / 180;// lat length

    /**
     * 查询附近的人
     * <a href="http://eslizn.com/archives/7/">参考</a>
     * 
     * @param lat 纬度
     * @param lon 经度
     * @param sex 性别
     * @param city 城市
     * @param district 区(县)
     * @param page 当前页面
     * @param pageSize 页数码
     * @return List<UserTrace> UserTrace集合
     */
    public List<UserTrace> search(Double lat, Double lon, Integer sex, Integer province, Integer city, int page,
            int pageSize) {

        double latLeft = lat - (Consts.dist.TRACE / LAT_LEN);
        double latRight = lat + (Consts.dist.TRACE / LAT_LEN);

        double lonLeft = lon - Consts.dist.TRACE / Math.abs(Math.cos(Math.toRadians(lat) * LAT_LEN));
        double lonRight = lon + Consts.dist.TRACE / Math.abs(Math.cos(Math.toRadians(lat) * LAT_LEN));

        page = page <= 0 ? 1 : page; // 不传值默认为1
        int offset = (page - 1) * pageSize; // 分页开始位置
        int size = pageSize;// 查询多少条信息

        UserTraceQuery query = new UserTraceQuery();
        query.setCity(city);
        query.setProvince(province);
        query.setDist(Consts.dist.TRACE);
        query.setLat(lat);
        query.setLatLeft(latLeft);
        query.setLatRight(latRight);
        query.setLon(lon);
        query.setLonLeft(lonLeft);
        query.setLonRight(lonRight);
        query.setSex(sex);
        query.setOffset(offset);
        query.setSize(size);
        return traceMapper.query(query);
    }

    /* =======================根据手机号码查询用户信息=============================== */

    /**
     * 根据手机号码查询用户信息
     * 
     * @param phone
     * @return User-Bean
     */
    public User getUser(String phone) {
        return userMapper.getUser(Consts.TablePrefix.USER
                + (int) (NumberUtils.toLong(phone) % Consts.TablePartition.USER), phone);
    }

    /* =========================隐藏用户============================== */

    /**
     * 隐藏自己,在user_trace表中,把自己设为不可见
     * 
     * @param id 用户ID
     * @return boolean-type
     */
    public boolean hide(Long userId) {
        try {
            return traceMapper.hide(userId) == 1;
        } catch (Exception e) {
            LOG.error("[hide] error userId: {}", userId, e);
        }
        return false;
    }

    /* ========================记录用户的信息================================ */

    /**
     * 记录用户的信息
     * 
     * @param trace 用户记录
     * @return boolean-type
     */
    public boolean trace(UserTrace trace) {
        try {
            return traceMapper.save(trace) >= 1;
        } catch (Exception e) {
            LOG.error("[trace] error {}", trace, e);
        }
        return false;
    }

    /* ========================创建互动信息=============================== */

    /**
     * 创建互动信息
     * 
     * @param fromUserId
     * @param toUserId
     * @param type
     * @param content
     * @return
     */
    /*
     * public boolean interact(Long fromUserId, Long toUserId, int type, String
     * content) {
     * if (interactMapper.has(fromUserId, toUserId, type) > 0) {
     * LOG.warn("has interact fromUserId:{},toUserId:{},type:{},content:{}",
     * fromUserId, toUserId, type, content);
     * return false;
     * }
     * Interact it = new Interact();
     * it.setContent(content);
     * it.setFromUserId(fromUserId);
     * it.setToUserId(toUserId);
     * it.setType(type);
     * try {
     * return interactMapper.add(it) == 1;
     * } catch (Exception e) {
     * LOG.error("[interact] error fromGzno:{},toGzno:{},type:{},content:{}",
     * fromUserId, toUserId, type, content,
     * e);
     * }
     * return false;
     * }
     */

    /* ========================更新用户的被赞数============================ */

    /**
     * 更新用户的被赞数
     * 
     * @param gzno
     * @return
     */
    public int like(Long userId) {
        try {
            return traceMapper.like(userId);
        } catch (Exception e) {
            LOG.error("[like] error userId:{}", userId, e);
        }
        return 0;
    }

    /* ========================添加相册相片============================== */

    /**
     * 
     * 添加相册相片
     * 
     * @param al
     * @return
     */
    public boolean addAlbum(Album album) {
        try {
            int flag = albumMapper.add(Consts.TablePrefix.ALBUM + album.getUserId() % Consts.TablePartition.ALBUM,
                    album);
            System.out.println(flag);
            return 1 == flag;
        } catch (Exception e) {
            LOG.error("[addAlbum] error userId:{},url:{}", album.getUserId(), album.getUrl(), e);
        }
        return false;
    }

    /* ==========================删除相册图片============================== */

    /**
     * 删除相册图片
     * 
     * @param gzno
     * @param crc
     * @return
     */
    public boolean deleteAlbum(Long userId, String crc) {
        try {
            String table = Consts.TablePrefix.ALBUM + userId % Consts.TablePartition.ALBUM;
            return 1 == albumMapper.delete(table, userId, crc);
        } catch (Exception e) {
            LOG.error("[deleteAlbum] error userId:{},crc:{}", userId, crc, e);
        }
        return false;
    }

    /* =========================获取用户的相册图片============================== */

    /**
     * 获取用户的相册图片
     * 
     * @param gzno
     * @return
     */
    public List<Album> getAlbum(Long userId) {
        try {
            String table = Consts.TablePrefix.ALBUM + userId % Consts.TablePartition.ALBUM;
            return albumMapper.query(table, userId);
        } catch (Exception e) {
            LOG.error("[getAlbum] error userId:{}", userId, e);
        }
        return Collections.emptyList();
    }

    /* =========================根据手机号码或咕吱号码查询用户信息============================= */

    /**
     * 根据手机号码或咕吱号码查询用户信息
     * 
     * @param userName 手机号码或咕吱号
     * @return User
     * */
    public User searchUser(String username) {
        try {
            int suffix = (int) (NumberUtils.toLong(username) % Consts.TablePartition.USER);
            System.out.println(suffix);
            String table = Consts.TablePrefix.USER + suffix;
            System.out.println(username);
            return userMapper.getUserByUserName(table, username);
        } catch (Exception e) {
            LOG.error("searchUser error", e);
        }
        return null;
    }

    /* ===========================获取用户资料============================== */

    /**
     * 获取用户资料
     * 
     * @param userId 用户ID
     * @return user
     * */
    public User getUserById(Long userId) {
        try {
            String table = Consts.TablePrefix.USER + (userId % Consts.TablePartition.USER);
            return userMapper.getUserById(table, userId);
        } catch (Exception e) {
            LOG.error("get user by id error", e);
        }

        return null;
    }

    /* ===========================通过phone获取用户资料================================ */
    public User getUserByPhone(Long phone) {
        try {
            String table = Consts.TablePrefix.USER + (phone % Consts.TablePartition.USER);
            return userMapper.getUserByPhone(table, phone);
        } catch (Exception e) {
            LOG.error("get user by id error", e);
        }

        return null;
    }

    /* ============================保存用户反馈信息============================= */

    /**
     * 保存用户反馈信息
     * 
     * @param content 反馈内容
     * @param userId 用户id
     * @return
     */
    public boolean feedBack(Long userId, String content) {
        try {
            return 1 == feedBackMapper.saveFeedBack(userId, content) ? true : false;
        } catch (Exception e) {
            LOG.error("save feedback content error", e);
        }
        return false;
    }

    /* =================================设置个人资料================================== */

    /**
     * 设置个人资料
     * 
     * @param userId 用户ID
     * @param birth 生日
     * @param job 职业
     * @param hobby 兴趣
     * @param school 学校
     * @param company 公司
     * @param intro 签名
     * @return resp
     * */
    public int setInfo(Long userId, User user) {
        try {
            String table = Consts.TablePrefix.USER + userId % Consts.TablePartition.USER;
            return userMapper.updateInfo(table, userId, user);
        } catch (Exception e) {
            LOG.error("set user info error", e);
        }

        return 0;

    }

    /* =================================添加好友================================== */

    /**
     * 添加好友
     * 
     * @param userId 用户ID
     * @param friendId 好友ID
     * @return boolean
     * */
    public boolean createFriendship(Long userId, Long friendId) {
        int result = 0;
        try {
            String table = Consts.TablePrefix.FRIENDSHIP + (userId % Consts.TablePartition.FRIENDSHIP);
            result = friendshipMapper.addFriendship(table, userId, friendId);

            table = Consts.TablePrefix.FRIENDSHIP + (friendId % Consts.TablePartition.FRIENDSHIP);
            result += friendshipMapper.addFriendship(table, friendId, userId);
        } catch (Exception e) {
            LOG.error("add friendship error", e);
        }
        return result >= 1 ? true : false;
    }

    /* ==============================查询好友列表============================== */
    /**
     * 查询好友列表
     * 
     * @param userId
     * @return List<Friendship>
     * */
    public List<Friendship> getFriendListById(Long userId) {
        try {
            String table = Consts.TablePrefix.FRIENDSHIP + (userId % Consts.TablePartition.FRIENDSHIP);
            return friendshipMapper.query(table, userId);
        } catch (Exception e) {
            LOG.error("get Friendship list error", e);
        }
        return null;
    }

    /**
     * 查询用户的黑名单列表
     * 
     * @param userId
     * */
    public List<Long> getUserBlacks(Long userId) {
        try {
            String table = Consts.TablePrefix.FRIENDSHIP + (userId % Consts.TablePartition.FRIENDSHIP);
            return friendshipMapper.queryMyBlack(table, userId);
        } catch (Exception e) {
            LOG.error("get getUserBlacks list error", e);
        }
        return Collections.emptyList();
    }

    /**
     * 查询拉黑用户的列表
     * 
     * @param userId
     * */
    public List<Long> getBeBlacker(Long userId) {
        try {
            return friendshipMapper.queryToBeBlacker(userId);
        } catch (Exception e) {
            LOG.error("get getBeBlacker list error", e);
        }
        return Collections.emptyList();
    }

    /* ==============================删除好友============================== */
    /**
     * 删除好友
     * 
     * @param userId 用户id
     * @param friendId 好友id
     * @return resp
     * */
    public boolean deleteFriendship(Long userId, Long friendId) {
        int result = 0;
        try {
            String table = Consts.TablePrefix.FRIENDSHIP + (userId % Consts.TablePartition.FRIENDSHIP);
            result = friendshipMapper.delete(table, userId, friendId);
        } catch (Exception e) {
            LOG.error("[deleteFriendship] error userId:{} , friendId:{}", userId, friendId, e);
        }
        return result == 1 ? true : false;
    }

    /* ==============================引导页============================== */
    /**
     * 保存引导页面上传的图片地址
     */
    public int saveUrl(String url) {
        try {
            return leadPageMapper.saveLeadPageUrl(url);
        } catch (Exception e) {
            LOG.error("save leadpage url error", e);
        }
        return 0;
    }

    /**
     * 获取引导页图片地址
     * 
     * @return
     */
    public String getLeadPage() {
        try {
            return leadPageMapper.query();
        } catch (Exception e) {
            LOG.error("get leadpage url error", e);
        }
        return null;
    }

    /* ==============================验证手机号是否存在============================== */
    /**
     * 验证手机号是否存在
     * 
     * @param phone
     * @return
     */
    public boolean verifyPhone(String phone) {
        try {
            int suffix = (int) NumberUtils.toLong(phone) % Consts.TablePartition.USER;
            String table = Consts.TablePrefix.USER + suffix;

            Integer count = null;
            count = forgetPasswordMapper.existPhone(table, phone);
            return (count != 0) ? true : false;
        } catch (Exception e) {
            LOG.error("verify phone number error", e);
        }
        return false;
    }

    /* ==============================根据咕吱号或手机号更新密码============================== */
    /**
     * 根据手机号更新密码
     * 
     * @param password 密码
     * @param gzno/phone　手机号
     * @return
     */
    public boolean updatePassword(String password, String phone) {
        try {
            int suffix = (int) (NumberUtils.toLong(phone)) % Consts.TablePartition.USER;
            String tableName = Consts.TablePrefix.USER + suffix;
            return 1 == forgetPasswordMapper.updatePassword(password, phone, tableName) ? true : false;
        } catch (Exception e) {
            LOG.error("save feedback content error", e);
        }
        return false;
    }

    /* ==============================获取咕吱签名列表============================== */
    /**
     * 获取咕吱签名列表
     * 
     * @param userId 用户ID
     * @return List<Intro>
     * */
    public List<Intro> getIntros(Long userId, Integer page, Integer pageSize) {
        try {
            String table = Consts.TablePrefix.INTRO + (int) (userId % Consts.TablePartition.INTRO);
            page = page <= 0 ? 1 : page;
            int offset = (page - 1) * pageSize;
            int size = pageSize;
            return introMapper.getIntros(table, userId, offset, size);
        } catch (Exception e) {
            LOG.error("get intro list error userId:{}", userId, e);
        }
        return Collections.emptyList();
    }

    /* ==============================统计咕吱签名============================== */
    /**
     * 统计咕吱签名
     * 
     * @param userId 用户ID
     * */
    public int getCount(Long userId) {
        try {
            String table = Consts.TablePrefix.INTRO + (int) (userId % Consts.TablePartition.INTRO);
            return introMapper.getCount(table, userId);
        } catch (Exception e) {
            LOG.error("get count error userId:{}", userId, e);
        }
        return 0;
    }

    /* ==============================添加咕吱签名============================== */
    /**
     * 添加咕吱签名
     * 
     * @param userId
     * 
     * @param Intro
     * @return resp
     * */
    public int addIntro(Intro intro) {

        try {
            String table = Consts.TablePrefix.INTRO + (int) (intro.getUserId() % Consts.TablePartition.INTRO);
            int re = introMapper.addIntro(table, intro);
            if (re > 0) {
                return introMapper.getCount(table, intro.getUserId());
            }
        } catch (Exception e) {
            LOG.error("add intro error intro:{}", intro, e);
        }
        return 0;
    }

    /* ==============================获取用户咕吱签名============================== */
    /**
     * 获取用户咕吱签名
     * 
     * @param userId 用户ID
     * @return intro
     * */
    public Intro getIntro(Long userId) {
        try {
            String table = Consts.TablePrefix.INTRO + (int) (userId % Consts.TablePartition.INTRO);
            int count = introMapper.getCount(table, userId);
            if (count > 0) {
                Intro intro = introMapper.getIntro(table, userId);
                intro.setCount(count);
                return intro;
            }
        } catch (Exception e) {
            LOG.error("get intro list error userId:{}", userId, e);
        }
        return null;
    }

    public boolean upadteIntroUrl(Intro intro) {
        try {
            String table = Consts.TablePrefix.INTRO + (int) (intro.getUserId() % Consts.TablePartition.INTRO);
            return 1 == introMapper.upadteIntroUrl(table, intro);
        } catch (Exception e) {
            LOG.error("update url of intro error intro:{}", intro, e);
        }
        return false;
    }

    /**
     * @param userId
     * @param blackUserId
     * @return
     */
    public boolean addBlack(Long userId, Long blackUserId) {
        String table = Consts.TablePrefix.FRIENDSHIP + (int) (userId % Consts.TablePartition.FRIENDSHIP);
        return friendshipMapper.addBlack(table, userId, blackUserId) == 1;
    }

    /**
     * @param dis
     * @return
     */
    public boolean createDiscussion(Discussion dis) {
        return disMapper.createDiscussion(dis) > 0;
    }

    /**
     * @param discussionId
     * @param memberIds
     */
    public boolean addDiscussionMember(Long discussionId, List<Long> memberIds) {
        String table = Consts.TablePrefix.DISCUSSION_MEMBER + discussionId % Consts.TablePartition.DISCUSSION_MEMBER;
        StringBuilder sb = new StringBuilder();
        for (Long memberId : memberIds) {
            sb.append('(').append(discussionId).append(',').append(memberId).append(')').append(',');
        }
        String sql = sb.substring(0, sb.length() - 1);
        return disMapper.batchAddDiscussionMember(table, sql) > 0;
    }

    /**
     * @param userId
     * @return
     */
    public List<Discussion> getUserDiscussions(Long userId) {
        List<Discussion> result = disMapper.queryDiscussions(userId);
        if (result == null) {
            result = Collections.emptyList();
        }
        return result;
    }

    /**
     * @param discussionId
     * @param userId
     */
    public boolean joinDiscussion(Long discussionId, Long userId) {
        String table = Consts.TablePrefix.DISCUSSION_MEMBER + discussionId % Consts.TablePartition.DISCUSSION_MEMBER;
        return disMapper.addDiscussionMember(table, discussionId, userId) > 0;
    }

    /**
     * @param discussionId
     * @param userId
     */
    public boolean quitDiscussion(Long discussionId, Long userId) {
        String table = Consts.TablePrefix.DISCUSSION_MEMBER + discussionId % Consts.TablePartition.DISCUSSION_MEMBER;
        return disMapper.deleteMember(table, discussionId, userId) > 0;
    }

    /**
     * @param discussionId
     */
    public void dissolveDiscussion(Long discussionId) {
        String table = Consts.TablePrefix.DISCUSSION_MEMBER + discussionId % Consts.TablePartition.DISCUSSION_MEMBER;
        disMapper.deleteDiscussion(discussionId);
        disMapper.deleteAllMember(table, discussionId);
    }

    /**
     * @param discussionId
     * @return
     */
    public List<Long> getDiscussionMember(Long discussionId) {
        String table = Consts.TablePrefix.DISCUSSION_MEMBER + discussionId % Consts.TablePartition.DISCUSSION_MEMBER;
        return disMapper.queryDiscussionMembers(table, discussionId);
    }

    /**
     * @param userId
     * @param string
     */
    public boolean updateHdLogo(Long userId, String hdlogo) {
        return updateUserByField(userId, "hdLogo", hdlogo);
    }

    private boolean updateUserByField(Long userId, String field, Object value) {
        String table = Consts.TablePrefix.USER + userId % Consts.TablePartition.USER;
        return userMapper.updateByField(table, field, value, userId) >= 0;
    }

    /**
     * @param userId
     * @param string
     */
    public boolean updateLogo(Long userId, String logo) {
        return updateUserByField(userId, "logo", logo);
    }

    /**
     * 获取我的帖子列表
     * 
     * @param userId 发帖人userId
     * @return
     */
    // public List<Posts> getMyPosts(Long userId) {
    // try {
    // return postsMapper.query(userId);
    // } catch (Exception e) {
    // LOG.error("[getMyPosts] error userId:{}", userId, e);
    // }
    // return Collections.emptyList();
    // }

    /**
     * 依据帖子类型获取帖子列表
     * 
     * @param postType
     * @return
     */
    // public List<Posts> searchPostByType(int postType) {
    // try {
    // return postsMapper.queryByCategory2(postType);
    // } catch (Exception e) {
    // LOG.error("[searchPostsByType] error postType:{}", postType, e);
    // }
    // return Collections.emptyList();
    // }

    // /**
    // * 根据帖子id获取回帖信息
    // *
    // * @param postId
    // * @return
    // */
    // public List<Reply> getCommentsBypostId(Long postsId) {
    // try {
    // return postsMapper.getComments(postsId);
    // } catch (Exception e) {
    // LOG.error("[GetCommentsByPostId Error]");
    // e.printStackTrace();
    // }
    // return null;
    // }

    /**
     * A向B打
     * */
    public boolean initiateInteract(Long fromUserId, Long toUserId) {
        try {
            int result = interactStateMapper.addUserIdInteract(fromUserId, toUserId);
            if (result >= 1) {
                int re = interactStateMapper.addFriendIdInteract(fromUserId, toUserId);
                if (re >= 1) {
                    return true;
                }
            }
        } catch (Exception e) {
            LOG.error("[initiate is error]", e);
        }
        return false;
    }

    /**
     * 对方打招呼
     * 
     * @param fromUserId 当前用户ID
     * @param toUserId 对方用户ID
     * */
    @Transactional(rollbackFor = Exception.class)
    public boolean agreeInteract(Long fromUserId, Long toUserId) {
        try {
            int flag = interactStateMapper.agreeInteract(fromUserId, toUserId);
            // if (flag >= 1) {
            // return createFriendship(fromUserId, toUserId);
            // }
            return flag == 2;
        } catch (Exception e) {
            LOG.error("[agree add friend is error]", e);
        }
        return false;
    }

    /**
     * 拒绝对象打招呼
     * 
     * @param fromUserId 当前用户ID
     * @param toUserId 对方用户ID
     * */
    public boolean rejectInteract(Long fromUserId, Long toUserId) {
        try {
            int result = interactStateMapper.rejectInteract(fromUserId, toUserId);
            if (result == 1) {
                return interactStateMapper.beReject(fromUserId, toUserId) == 1;
            }
        } catch (Exception e) {
            LOG.error("[]", e);
        }
        return false;
    }

    /**
     * 拒绝对象打招呼
     * 
     * @param fromUserId 当前用户ID
     * @param toUserId 对方用户ID
     * */
    public boolean recoverInteract(Long fromUserId, Long toUserId) {
        try {
            int result = interactStateMapper.recoverInteract(fromUserId, toUserId);
            if (result == 1) {
                return 1 == interactStateMapper.beRecover(fromUserId, toUserId);
            }
        } catch (Exception e) {
            LOG.error("[]", e);
        }
        return false;
    }

    /**
     * 创建帖子
     * 
     * @param posts
     * @return
     */
    public boolean createPosts(Posts posts) {

        Integer tableIndex = Consts.POSTS_INDEX.get("" + posts.getProvince());
        if (tableIndex == null) {
            tableIndex = 0;
        }
        String table = Consts.TablePrefix.POSTS + tableIndex;
        try {
            return 1 == postsMapper.create(table, posts, tableIndex);
        } catch (Exception e) {
            LOG.error("[create posts] error", e);
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 检查是否已点赞
     * 
     * @param fromUserId
     * @param toUserId
     * @return
     */
    public boolean checkLike(Long fromUserId, Long toUserId) {
        try {
            return (1 == userMapper.existLike(fromUserId, toUserId)) ? true : false;
        } catch (Exception e) {
            LOG.error("[check ever like error]");
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 检查是帖子否已点赞
     * 
     * @param fromUserId
     * @param toUserId
     * @return
     */
    public boolean checkPostsLike(Long userId, Long postsId) {
        try {
            String table = Consts.TablePrefix.REPLY + postsId % Consts.TablePartition.POSTS + "_" + postsId
                    % Consts.TablePartition.REPLY;
            return postsMapper.liked(table, userId, postsId) >= 1;
        } catch (Exception e) {
            LOG.error("[checkPostsLike] error ,userId:{},postsId:{}", userId, postsId, e);
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 添加个人资料点赞记录到数据库
     * 
     * @param fromUserId 点赞人userId
     * @param toUserId 被点赞人userId
     * @param fromUserImid 点赞人环信id
     * @param toUserImid 被点赞人环信id
     * @return
     */
    public boolean addUserInfoLike(Long fromUserId, Long toUserId, String fromUserImid, String toUserImid) {

        try {
            return (1 == userMapper.addLike(fromUserId, toUserId, fromUserImid, toUserImid)) ? true : false;
        } catch (Exception e) {
            LOG.error("[addUserInfoLike error]");
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 更新user_trace表中userId对应记录的likes字段自增1
     * 
     * @param toUserId
     * @return
     */
    public int updateLikes(Long toUserId, int likes) {
        try {
            if (1 == userMapper.updateLike(toUserId, likes)) {
                return 1;
            }
            String table = Consts.TablePrefix.USER + toUserId % Consts.TablePartition.USER;
            String gzno = userMapper.getGznoById(table, toUserId);
            return userMapper.initLike(gzno, toUserId, userMapper.getSexByUserId(table, toUserId));
        } catch (Exception e) {
            LOG.error("[updateLikes error]");
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 获取用户资料点赞数
     * 
     * @param toUserId
     * @return
     */
    public int getLikesByUserId(Long toUserId) {
        try {
            Integer likes = userMapper.getLikes(toUserId);
            if (likes == null) {
                return 0;
            }
            return likes;
        } catch (Exception e) {
            LOG.error("[getLikesByUserId error]");
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 获取点赞者信息
     * 
     * @param fromUserId
     * @return
     */
    public User getLiker(Long fromUserId) {
        try {
            String tableName = Consts.TablePrefix.USER + fromUserId % Consts.TablePartition.USER;
            User user = userMapper.getLikerInfo(tableName, fromUserId);
            return user;
        } catch (Exception e) {
            LOG.error("getLiker ERROR");
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取logo
     * 
     * @param fromUserId
     * @return
     */
    public String getLogo(Long fromUserId) {
        try {
            String tableName = Consts.TablePrefix.USER + fromUserId % Consts.TablePartition.USER;
            String logo = userMapper.getLogo(tableName, fromUserId);
            return logo;
        } catch (Exception e) {
            LOG.error("GET logo error");
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取昵称
     * 
     * @param fromUserId
     * @return
     */
    public String getNick(Long fromUserId) {
        try {
            String tableName = Consts.TablePrefix.USER + fromUserId % Consts.TablePartition.USER;
            return userMapper.getNick(tableName, fromUserId);
        } catch (Exception e) {
            LOG.error("GET NICK ERROR");
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取userId
     * 
     * @param phone
     * @return
     */
    public int getUserIdByPhone(String phone) {
        try {
            Long phoneNumber = Long.parseLong(phone);
            String tableName = Consts.TablePrefix.USER + phoneNumber % Consts.TablePartition.USER;
            return userMapper.getUserId(tableName, phoneNumber);
        } catch (Exception e) {
            LOG.error("[GetUserById] error phone:{}", phone, e);
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * @param userId
     * @return
     */
    public List<InteractState> getUserFriends(Long userId) {
        try {
            return interactStateMapper.getByUserId(userId);
        } catch (Exception e) {
            LOG.error("[getUserFriends] error userId:{}", userId, e);
        }
        return Collections.emptyList();
    }

    /**
     * @param userIds
     * @return
     */
    public List<User> batchGetUser(List<Long> userIds) {
        // 按在同一张表的用户划分userId
        Map<Integer, List<Long>> map = new HashMap<Integer, List<Long>>();
        for (Long userId : userIds) {
            System.out.println("id==" + userId);
            int idx = (int) (userId % Consts.TablePartition.USER);
            List<Long> sameTableUserIds = map.get(idx);
            if (sameTableUserIds == null) {
                sameTableUserIds = new ArrayList<Long>();
                map.put(idx, sameTableUserIds);
            }
            sameTableUserIds.add(userId);
        }
        List<User> result = new ArrayList<User>();
        for (Integer idx : map.keySet()) {
            try {
                List<User> users = userMapper.getUserByIds(Consts.TablePrefix.USER + idx,
                        StringUtils.join(map.get(idx), ','));
                if (users != null) {
                    result.addAll(users);
                }
            } catch (Exception e) {
                LOG.error("[userMapper.getUserByIds] error", e);
            }
        }
        return result;
    }

    public InteractState getInteract(Long fromUserId, Long toUserId) {
        try {
            return interactStateMapper.getInteract(fromUserId, toUserId);
        } catch (Exception e) {
            LOG.error("[get interact] is error", e);
        }
        return null;
    }

    /**
     * @param fromUserId
     * @param toUserId
     * @return
     */
    public boolean blackInteract(Long fromUserId, Long toUserId, InteractState st) {
        try {
            // 如果是被对方拉黑了，那么状态要改为互相拉黑
            if (st.getState() == 4) {
                interactStateMapper.blackEachOther(fromUserId, toUserId);
            } else {
                interactStateMapper.black(fromUserId, toUserId);
                interactStateMapper.beBlack(fromUserId, toUserId);
            }
            return true;
        } catch (Exception e) {
            LOG.error("[blackInteract] error", e);
        }
        return false;
    }

    /**
     * @param fromUserId
     * @param toUserId
     * @return
     */
    public boolean deleteInteract(Long fromUserId, Long toUserId) {
        try {
            interactStateMapper.delete(fromUserId, toUserId);
            interactStateMapper.beDelete(fromUserId, toUserId);
            return true;
        } catch (Exception e) {
            LOG.error("[blackInteract] error", e);
        }
        return false;
    }

    /**
     * 通过phone获取imid
     * 
     * @param phone phone
     * @return imid
     */
    public String getImidByUserId(String phone) {
        try {
            String tableName = Consts.TablePrefix.USER + (int) (NumberUtils.toLong(phone)) % Consts.TablePartition.USER;
            return userMapper.getImidByPhone(tableName, phone);

        } catch (Exception e) {
            LOG.error("GetImidByUserId Error");
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 通过phone获取密码
     * 
     * @param phone
     * @return
     */
    public String getOldPassword(String phone) {
        String tableName = Consts.TablePrefix.USER + ((NumberUtils.toLong(phone))) % Consts.TablePartition.USER;
        System.out.println("-----------tableName:" + tableName);
        return userMapper.getOldPassword(tableName, phone);
    }

    /*
     * @param fromUserId
     * 
     * @param toUserId
     * 
     * @return
     */
    public boolean unblackInteract(Long fromUserId, Long toUserId, InteractState st) {
        try {
            // 如果是互相拉黑
            if (st.getState() == 6) {
                interactStateMapper.unblack(fromUserId, toUserId);
                interactStateMapper.beUnBlack(fromUserId, toUserId);
            } else {// 如果是拉黑对方
                interactStateMapper.agreeInteract(fromUserId, toUserId);
            }
            return true;
        } catch (Exception e) {
            LOG.error("[blackInteract] error", e);
        }
        return false;
    }

    /**
     * 默认推荐10个
     * 
     * @param userId
     * @return
     */
    public List<Long> getRecommendFriends(Long userId) {
        return interactStateMapper.getRecommend(userId);
    }

    /**
     * @param imids
     * @return
     */
    public List<Long> getUserIdByImids(String imids) {
        List<String> imidList = Arrays.asList(StringUtils.trim(imids).split(","));
        if (CollectionUtils.isEmpty(imidList)) {
            return Collections.emptyList();
        }
        StringBuilder sb = new StringBuilder();
        for (String str : imidList) {
            sb.append("'" + str + "',");
        }
        String imidss = sb.toString().substring(0, sb.length() - 1);
        System.out.println("imidss=============:" + imidss);
        return userMapper.getUserIdByImids(imidss);
    }

    /**
     * 获取所有帖子类型
     * 
     * @return
     */
    @Cacheable(value = "resourceCache", key = "'getAllPostsCategory' + #date")
    public List<PostsCategory> getAllPostsCategory(String date) {
        System.out.println("======a=======");
        try {
            List<PostsCategory> listPosts = postsMapper.getAllCategory();
            System.out.println("....listPosts:" + listPosts);
            return listPosts;
        } catch (Exception e) {
            LOG.error("Get all postsCategory Error...", e);
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 搜索附近的帖子
     * 
     * @param lat
     * @param lon
     * @param province
     * @param page
     * @param pageSize
     * @return
     */
    public List<Posts> queryNearbyPosts(Long userId, Double lat, Double lon, Integer province, Integer page,
            Integer pageSize) {

        double latLeft = lat - (Consts.dist.POSTS / LAT_LEN);
        double latRight = lat + (Consts.dist.POSTS / LAT_LEN);

        double lonLeft = lon - Consts.dist.POSTS / Math.abs(Math.cos(Math.toRadians(lat) * LAT_LEN));
        double lonRight = lon + Consts.dist.POSTS / Math.abs(Math.cos(Math.toRadians(lat) * LAT_LEN));

        PostsQuery query = new PostsQuery();
        query.setOffset((page - 1) * pageSize);
        query.setSize(pageSize);
        query.setLat(lat);
        query.setLon(lon);
        query.setProvince(province);
        query.setLatLeft(latLeft);
        query.setLatRight(latRight);
        query.setLonLeft(lonLeft);
        query.setLonRight(lonRight);
        query.setDist(Consts.dist.POSTS);
        query.setUserId(userId);
        return searchPosts(query);
    }

    /**
     * 按主题类型搜索的帖子
     * 
     * @param lat
     * @param lon
     * @param province
     * @param page
     * @param pageSize
     * @return
     */
    public List<Posts> queryPostsByCategory(Long userId, Double lat, Double lon, Integer province, Integer category,
            Integer page, Integer pageSize) {
        PostsQuery query = new PostsQuery();
        query.setOffset((page - 1) * pageSize);
        query.setSize(pageSize);
        query.setLat(lat);
        query.setLon(lon);
        query.setProvince(province);
        query.setCategory(category);
        query.setDist(Consts.dist.POSTS);
        query.setUserId(userId);
        return searchPosts(query);
    }

    /**
     * 按标题关键字搜索的帖子
     * 
     * @param lat
     * @param lon
     * @param province
     * @param page
     * @param pageSize
     * @return
     */
    public List<Posts> queryPostsBySearchKey(Long userId, Double lat, Double lon, Integer province, String searchKey,
            Integer page, Integer pageSize) {

        PostsQuery query = new PostsQuery();
        query.setOffset((page - 1) * pageSize);
        query.setSize(pageSize);
        query.setLat(lat);
        query.setLon(lon);
        query.setProvince(province);
        query.setSearchKey(UnicodeConverter.toEncodedUnicode(searchKey, false));
        query.setDist(Consts.dist.POSTS);
        query.setUserId(userId);
        return searchPosts(query);
    }

    private List<Posts> searchPosts(PostsQuery query) {
        Integer tableIndex = Consts.POSTS_INDEX.get("" + query.getProvince());
        if (tableIndex == null) {
            tableIndex = 0;
        }
        String table = Consts.TablePrefix.POSTS + tableIndex;
        query.setTable(table);

        List<Posts> result = postsMapper.query(query);
        if (CollectionUtils.isEmpty(result)) {
            return result;
        }
        List<Long> postsIds = addPostsAlbum(result);// 添加相册信息
        if (query.getUserId() != null) {
            addPostsLiked(result, postsIds, query.getUserId());// 添加点赞信息
        }
        return result;
    }

    /**
     * 添加帖子点赞信息
     * 
     * @param result
     */
    private void addPostsLiked(List<Posts> result, List<Long> postsIds, Long userId) {
        if (CollectionUtils.isEmpty(postsIds)) {
            return;
        }
        List<Long> likedPosts = queryLikedPostsId(postsIds, userId);
        for (Posts p : result) {
            for (Long l : likedPosts) {
                if (p.getId().longValue() == l.longValue()) {
                    p.setLiked(1);
                    break;
                }
            }
        }
    }

    /**
     * @param postsId
     * @param userId
     * @return
     */
    public int queryLikedByPostsIdAndUserID(Long postsId, Long userId) {
        try {
            String table = Consts.TablePrefix.REPLY + postsId % Consts.TablePartition.POSTS + "_" + postsId
                    % Consts.TablePartition.REPLY;
            int result = postsMapper.queryLikedByPostsIdAndUserID(table, postsId, userId);
            if (result >= 1) {
                return 1;
            }
        } catch (Exception e) {
            LOG.error("[addPostsAlbum] error", e);
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * @param result
     */
    private List<Long> addPostsAlbum(List<Posts> result) {
        if (CollectionUtils.isEmpty(result)) {
            return Collections.emptyList();
        }
        List<Long> postsIds = new ArrayList<Long>();
        for (Posts p : result) {
            postsIds.add(p.getId());
        }
        String table = Consts.TablePrefix.POSTS_ALBUM + postsIds.get(0) % Consts.TablePartition.POSTS_ALBUM;
        List<PostsAlbum> albums = postsMapper.getAlbum(table, StringUtils.join(postsIds, ","));
        Map<Long, List<PostsAlbum>> map = new HashMap<Long, List<PostsAlbum>>();
        for (PostsAlbum pa : albums) {
            List<PostsAlbum> list = map.get(pa.getPostsId());
            if (list == null) {
                list = new ArrayList<PostsAlbum>();
                map.put(pa.getPostsId(), list);
            }
            list.add(pa);
        }
        for (Posts p : result) {
            p.setAlbums(map.get(p.getId()));
        }
        return postsIds;
    }

    /**
     * 根据postsId 获取点赞数
     * 
     * @param postId 帖子id
     * @return
     */
    public int getPostsLikes(Long postsId) {
        String table = Consts.TablePrefix.POSTS + postsId % Consts.TablePartition.POSTS;
        try {
            return postsMapper.getLikes(table, postsId);
        } catch (Exception e) {
            LOG.error("[getPostsLikes] Error postsId:{}", postsId, e);
        }
        return 0;
    }

    /**
     * 根据postsId 获取回复数
     * 
     * @param postsId
     * @return
     */
    public int getPostsReplys(Long postsId) {
        String table = Consts.TablePrefix.POSTS + postsId % Consts.TablePartition.POSTS;
        try {
            return postsMapper.getReplys(table, postsId);
        } catch (Exception e) {
            LOG.error("[getPostsReplys] Error postsId:{}", postsId, e);
        }
        return 0;
    }

    /**
     * 创建回复信息
     * 
     * @param reply
     */
    public boolean addReply(Reply reply) {

        // 回复表有两级分表信息
        // 第一级 帖子ID%34 第二级 帖子ID%4
        int first = reply.getPostsId().intValue() % Consts.TablePartition.POSTS;
        int second = reply.getPostsId().intValue() % Consts.TablePartition.REPLY;
        String table = Consts.TablePrefix.REPLY + first + "_" + second;

        try {
            int result = postsMapper.addReply(table, reply, second);
            if (result >= 1) {
                if (reply.getTypes() == Reply.REPLY_TYPE_LIKE) {
                    // 更新表的点赞数
                    postsMapper.like(Consts.TablePrefix.POSTS + first, reply.getPostsId());
                } else {
                    postsMapper.reply(Consts.TablePrefix.POSTS + first, reply.getPostsId());

                }
                return true;
            }
        } catch (Exception e) {
            LOG.error("addReply error postsId:{},userId:{},type:{}", reply.getPostsId(), reply.getUserId(),
                    reply.getTypes(), e);
        }
        return false;
    }

    /**
     * @param userId
     * @param province
     * @return
     */
    public List<Posts> queryByUserId(Long userId, Integer province, Long maxPostsId, Integer page, Integer pageSize) {
        Integer tableIndex = Consts.POSTS_INDEX.get("" + province);
        if (tableIndex == null) {
            tableIndex = 0;
        }
        String table = Consts.TablePrefix.POSTS + tableIndex;
        int offset = (page - 1) * pageSize;
        int size = pageSize;
        List<Posts> result = postsMapper.queryByUserId(table, userId, maxPostsId, offset, size);
        List<Long> postsIds = addPostsAlbum(result);
        addPostsLiked(result, postsIds, userId);// 添加点赞信息
        return result;
    }

    /**
     * 查询跟用户相关的reply
     * 
     * @param userId
     * @param province
     * @param maxId
     * @param page
     * @param pageSize
     * @return
     */
    public List<Reply> queryReplyByUserId(Long userId, Integer province, Integer page, Integer pageSize) {
        Integer tableIndex = Consts.POSTS_INDEX.get("" + province);
        if (tableIndex == null) {
            tableIndex = 0;
        }
        String table = Consts.TablePrefix.REPLY + tableIndex;
        int offset = (page - 1) * pageSize;
        int size = pageSize;
        List<Reply> result = postsMapper.queryReplyByUserId(table, userId, offset, size);
        return result;
    }

    /**
     * 删除帖子
     * 
     * @param postsId
     */
    public boolean delPosts(Long postsId) {
        try {
            // 1. 删除帖子
            int index = postsId.intValue() % Consts.TablePartition.POSTS;
            String table = Consts.TablePrefix.POSTS + index;
            postsMapper.delPosts(table, postsId);
            // 2. 删除对应的回复
            table = Consts.TablePrefix.REPLY + index + "_" + postsId.intValue() % Consts.TablePartition.REPLY;
            postsMapper.delReplyByPostsId(table, postsId);
            // 3. 删除对应的相册
            table = Consts.TablePrefix.POSTS_ALBUM + index;
            postsMapper.delAlbum(table, postsId);

            return true;
        } catch (Exception e) {
            LOG.error("[delPosts] error postsId:{}", postsId, e);
        }
        return false;
    }

    /**
     * @param postsId
     * @param replyId
     * @return
     */
    public boolean delReply(Long postsId, Long replyId) {
        try {
            int index = postsId.intValue() % Consts.TablePartition.POSTS;
            String table = Consts.TablePrefix.REPLY + index + "_" + postsId.intValue() % Consts.TablePartition.REPLY;
            int deduct = postsMapper.delReplyById(table, replyId);
            // 减少帖子的评论数
            postsMapper.deductReplys(Consts.TablePrefix.POSTS + index, postsId, deduct);
            return true;
        } catch (Exception e) {
            LOG.error("[delPosts] error postsId:{}", postsId, e);
        }
        return false;

    }

    // /**
    // * 根据postId获取评论数
    // *
    // * @param postId 帖子id
    // * @return
    // */
    // public int countComments(int postId) {
    // try {
    // return postsMapper.countComments(postId);
    // } catch (Exception e) {
    // LOG.error("[Get countComments Error]");
    // e.printStackTrace();
    // }
    // return 0;
    // }

    /**
     * @param id
     * @return
     */
    public PostsCategory getPostsCategoryById(Long id) {
        try {
            return postsMapper.getCategoryById(id);
        } catch (Exception e) {
            LOG.error("getPostsCategory error id:{}", id, e);
        }
        return null;
    }

    public boolean upadteAlbum(Album album) {
        try {
            String table = Consts.TablePrefix.ALBUM + (album.getUserId() % Consts.TablePartition.ALBUM);
            return 1 == albumMapper.update(table, album);
        } catch (Exception e) {
            LOG.error("[update album is error album:{}]", album);
        }
        return false;
    }

    /**
     * @param postsId
     * @return
     */
    public Posts getPostsById(Long postsId) {
        String table = Consts.TablePrefix.POSTS + postsId % Consts.TablePartition.POSTS;
        Posts posts = postsMapper.getById(table, postsId);
        if (posts == null) {
            return null;
        }
        table = Consts.TablePrefix.POSTS_ALBUM + postsId % Consts.TablePartition.POSTS_ALBUM;
        List<PostsAlbum> albums = postsMapper.getAlbum(table, postsId + "");
        if (CollectionUtils.isNotEmpty(albums)) {
            posts.setAlbums(albums);
        }

        return posts;
    }

    /**
     * @param postsId
     * @return
     */
    public Posts getPostsNoAlbumById(Long postsId) {
        String table = Consts.TablePrefix.POSTS + postsId % Consts.TablePartition.POSTS;
        Posts posts = postsMapper.getById(table, postsId);
        if (posts == null) {
            return null;
        }
        return posts;
    }

    /**
     * @param postsId
     * @param minId 最小的评论ID
     * @param page
     * @param pageSize
     * @return
     */
    public List<ReplyResp> queryCommentsByPostsId(Long postsId, Long minId, Integer page, Integer pageSize) {
        String table = Consts.TablePrefix.REPLY + postsId % Consts.TablePartition.POSTS + "_" + postsId
                % Consts.TablePartition.REPLY;
        return postsMapper.queryCommentsByPostsId(table, postsId, minId, (page - 1) * pageSize, pageSize);
    }

    /**
     * @param postsId
     * @param replyId
     * @param i
     * @param j
     * @return
     */
    public List<ReplyResp> queryCommentReply(Long postsId, Long replyId, Long minId, Integer page, Integer pageSize) {
        String table = Consts.TablePrefix.REPLY + postsId % Consts.TablePartition.POSTS + "_" + postsId
                % Consts.TablePartition.REPLY;
        return postsMapper.queryCommentReply(table, postsId, replyId, minId, (page - 1) * pageSize, pageSize);
    }

    /**
     * @param postsId
     * @param replyId
     * @return
     */
    public int queryCommentTotalReply(Long postsId, Long replyId, Long maxId) {
        String table = Consts.TablePrefix.REPLY + postsId % Consts.TablePartition.POSTS + "_" + postsId
                % Consts.TablePartition.REPLY;
        return postsMapper.queryCommentTotalReply(table, postsId, replyId, maxId);
    }

    /**
     * @param postsId
     * @param replyId
     * @return
     */
    public List<Long> queryLikedPostsId(List<Long> postsIds, Long userId) {

        if (CollectionUtils.isEmpty(postsIds)) {
            return Collections.emptyList();
        }
        Long postsIdTemplate = postsIds.get(0);
        String table = Consts.TablePrefix.REPLY + postsIdTemplate % Consts.TablePartition.POSTS;

        Map<Integer, List<Long>> listArray = new HashMap<Integer, List<Long>>() {
            private static final long serialVersionUID = 3240014164151748744L;

            {
                for (int i = 0; i < Consts.TablePartition.REPLY; i++) {
                    put(i, null);
                }
            }
        };

        for (Long l : postsIds) {
            int i = l.intValue() % Consts.TablePartition.REPLY;
            List<Long> list = listArray.get(i);
            if (list == null) {
                list = new ArrayList<Long>();
                listArray.put(i, list);
            }
            list.add(l);
        }
        List<Long> list = listArray.get(0);
        String list0 = list == null ? null : StringUtils.join(list, ",");
        list = listArray.get(1);
        String list1 = list == null ? null : StringUtils.join(list, ",");
        list = listArray.get(2);
        String list2 = list == null ? null : StringUtils.join(list, ",");
        list = listArray.get(3);
        String list3 = list == null ? null : StringUtils.join(list, ",");
        return postsMapper.queryLikedPostsId(table, userId, list0, list1, list2, list3);
    }

    /**
     * @param userId
     * @param replyId
     * @return
     */
    public Reply queryReplyById(Long postsId, Long replyId) {
        String table = Consts.TablePrefix.REPLY + postsId % Consts.TablePartition.POSTS + "_" + postsId
                % Consts.TablePartition.REPLY;
        return postsMapper.queryReplyById(table, replyId);
    }

    /**
     * @param postsId
     * @param replyId
     * @return
     */
    public ReplyResp queryReplyRespById(Long postsId, Long replyId) {
        String table = Consts.TablePrefix.REPLY + postsId % Consts.TablePartition.POSTS + "_" + postsId
                % Consts.TablePartition.REPLY;
        return postsMapper.queryReplyRespById(table, replyId);
    }

    /**
     * 记录用户注册的省市人数
     * 
     * @param province
     * @param city
     * @return
     */
    public int updateUserCount(Integer provinceCode, Integer cityCode) {
        try {
            return userMapper.updateUserCount(provinceCode, cityCode);
        } catch (Exception e) {
            LOG.error("[update user_count table error]", e);
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * @param al
     */
    public void addPostsAlbum(PostsAlbum al) {
        try {
            String table = Consts.TablePrefix.POSTS_ALBUM + al.getPostsId() % Consts.TablePartition.POSTS_ALBUM;
            postsMapper.addAlbum(table, al);
        } catch (Exception e) {
            LOG.error("[addPostsAlbum] error", e);
            e.printStackTrace();
        }
    }

    // 按在同一张表的用户划分userId
    /*
     * Map<Integer, List<Long>> map = new HashMap<Integer, List<Long>>();
     * for (Long userId : userIds) {
     * int idx = (int) (userId % Consts.TablePartition.USER);
     * List<Long> sameTableUserIds = map.get(idx);
     * if (sameTableUserIds == null) {
     * sameTableUserIds = new ArrayList<Long>();
     * map.put(idx, sameTableUserIds);
     * }
     * sameTableUserIds.add(userId);
     * }
     * List<User> result = new ArrayList<User>();
     * for (Integer idx : map.keySet()) {
     * try {
     * List<User> users = userMapper.getUserByIds(Consts.TablePrefix.USER + idx,
     * StringUtils.join(map.get(idx), ','));
     * if (users != null) {
     * result.addAll(users);
     * }
     * } catch (Exception e) {
     * LOG.error("[userMapper.getUserByIds] error", e);
     * }
     * }
     */

    /**
     * 批量获取咕吱签名
     * */
    public List<Intro> getIntrByIds(List<Long> ids) {
        System.out.println(ids);
        Map<Integer, List<Long>> map = new HashMap<Integer, List<Long>>();

        for (Long userId : ids) { // 遍历 ids 1,20,41,78
            int idx = (int) (userId % Consts.TablePartition.INTRO); // 分表_数
            List<Long> sameTableUserIdxs = map.get(idx); //
            if (sameTableUserIdxs == null) { //
                sameTableUserIdxs = new ArrayList<Long>();
                map.put(idx, sameTableUserIdxs);
            }
            sameTableUserIdxs.add(userId);
        }
        List<Intro> result = new ArrayList<>();
        for (Integer idx : map.keySet()) {
            try {
                System.out.println("*******" + idx + "===" + StringUtils.join(map.get(idx), ","));
                List<Intro> intros = introMapper.getIntrosById(Consts.TablePrefix.INTRO + idx,
                        StringUtils.join(map.get(idx), ","));
                if (intros != null && intros.size() > 0) {
                    result.addAll(intros);
                }
            } catch (Exception e) {
                LOG.error("[]", e);
            }
        }
        System.out.println(">>>>>" + result.size());
        return result;
    }

    public void updateIntroToUserTrace(Long userId, String content) {

        try {
            introMapper.updateIntroToUserTrace(userId, content);
        } catch (Exception e) {
            LOG.error("[]", e);
        }

    }

    /**
     * 根据username获取userId
     * 
     * @param username 手机号或咕吱号
     * @return
     */
    public Long getUserIdByUsername(String username) {
        int suffix = (int) (NumberUtils.toLong(username) % Consts.TablePartition.USER);
        String tableName = Consts.TablePrefix.USER + suffix;
        return userMapper.getUserIdByUserName(tableName, username);
    }

    public boolean addUserBackground(Integer code, String fileName) {

        try {
            return 1 == userSetMapper.addUserBackground(code, fileName);
        } catch (Exception e) {

        }
        return false;

    }

    public String getUserBackground(Integer code) {
        try {
            return userSetMapper.getUserBackground(code);
        } catch (Exception e) {

        }
        return null;
    }

    /**
     * 批量注册用户
     * 
     * @param gzno
     * @param pwd
     * @param province
     * @param city
     * @param string
     * @param birth
     * @param string2
     * @param string3
     * @param phone
     * @param age
     * @param sex
     * @param imid
     */
    public int genUser(User user, String table, int radix) {

        return userMapper.genUser(user, table, radix);
    }

    /**
     * 批量添加用户时加入用户当前位置信息
     * 
     * @param gzno
     * @param userId
     * @param d
     * @param e
     * @param sex
     * @param city
     * @param province
     * @param string
     * @return
     */
    public int addTrace(String gzno, int userId, double lat, double lon, int sex, int city, int province, String intro) {

        return traceMapper.addTrace(gzno, userId, lat, lon, sex, city, province, intro);
    }

    /**
     * 获取某个省的用户数
     * 
     * @param locateProv
     * @return
     */
    public int countProvince(Integer province, Integer city, Integer locateProv) {

        return traceMapper.countProvince(province, city, locateProv);

    }

    /**
     * @param province
     * @return
     */
    public int countUserProvince(Integer province) {
        return traceMapper.countUserProvince(province);
    }

    /**
     * @param city
     * @return
     */
    public int countUserCity(Integer city) {
        return traceMapper.countUserCity(city);
    }

}
